<?php

namespace App\Clients;

use App\Constants\ClientConstants;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class CrmClient extends Request
{

    public $groupMode = false;
    public $useGroupApi = false;

    /**
     * @throws \Exception
     */
    public function __construct($data = null)
    {
        $data = $data ?: json_decode(admin_setting('crm_account'), true);

        if (!Arr::has($data, ['domain', 'username', 'password']))
            throw new \Exception("错误的信息,没法登录crm");

        $account = Arr::only($data, ['username', 'password']);
        $domain = Arr::get($data, 'domain');
        $this->groupMode = !!admin_setting('group_mode');
        $this->useGroupApi = !!admin_setting('use_group_api');

        parent::__construct($account, $domain);

    }


    /**
     * 查看登录状态
     * @return bool
     * @throws GuzzleException
     */
    public function isLogin(): bool
    {
        $response = $this->get('/');
        $response = $response->getBody()->getContents();
        return !preg_match('/用户登录/', $response);
    }

    /**
     * 获取账号的登录状态
     * @return bool
     * @throws GuzzleException
     */
    public function loginStatus(): bool
    {
        if (!$this->isLogin()) {
            return $this->login();
        }
        return true;
    }

    /**
     * Crm登录方法
     * @return bool
     * @throws GuzzleException
     */
    public function login(): bool
    {
        $response = $this->post('/Account/Auth/Login', [
            'form_params' => $this->account,
        ]);
        $contents = $response->getBody()->getContents();
        $result = json_decode($contents, true);
        $code = data_get($result, 'statusCode', 0);
        $status = $code === "200" || $code === "201";
        $this->switchGroup();
        return $status;
    }

    public function switchGroup()
    {
        if ($this->groupMode && $groupId = admin_setting('group_id')) {
            $this->get("/Home/JumpOutSwitchOrg?orgId=$groupId");
        }
    }

    public function ReservationTempCustSearchIndex($data): \Illuminate\Support\Collection
    {
        $data = array_merge(ClientConstants::TEMP_API_BASE_PARAMS, $data);
        $url = $this->useGroupApi ? "/Reservation/TempCustInfo/Indexorgid" : "/Reservation/TempCustInfo/Index";

        $response = $this->post($url, [
            'form_params' => $data
        ]);
        $body = $response->getBody()->getContents();

        if (!preg_match("/建档时间/", $body))
            throw new \Exception('ReservationTempCustSearchIndex接口失败.');
        $t = parserHtmlTableToObject($body, '.table-striped', 'innerText');
        $result = collect($t)
            ->filter(function ($item) {
                return !!data_get($item, '媒介');
            });
        return $result;
    }

    public function ReservationTempCustSearchCompayIndex()
    {
        $url = "/Reservation/TempCustSearch/Index";

        $response = $this->get($url);
        return $response->getBody()->getContents();
    }

    public function ReservationTempCustInfoIndex($data): ?\Illuminate\Support\Collection
    {
        if (!$this->loginStatus()) {
            Log::error("查询建档失败,系统登录失败");
            return null;
        }
        $data = array_merge([
            'pageCurrent' => 1,
        ], $data);
        $url = "/Reservation/TempCustInfo/Index";
        if ($this->useGroupApi) {
            $url = "/Reservation/TempCustInfo/IndexToGroup";
            $this->switchGroup();
        }
        $response = $this->get($url, [
            'query' => $data
        ]);
        $body = $response->getBody()->getContents();

        if (!str_contains($body, "添加预约")) {
            Log::error(" Reservation Temp CustInfo Index 接口失败", [$body]);
            return null;
        }
        $t = parserHtmlTableToObject($body, '.table', 'innerText');
        $result = collect($t)
            ->filter(function ($item) {
                return !!data_get($item, '建档时间');
            });

        return $result;
    }

    public function ReservationTempCustInfoCreateView()
    {
        $url = $this->useGroupApi ? "Reservation/TempCustInfo/TempOrgCreate" : "Reservation/TempCustInfo/Create";

        $response = $this->get("$url?phone=11143214321");
        return $response->getBody()->getContents();
    }

    public function ReservationTempCustInfoCreateApi($data)
    {
        $url = "Reservation/TempCustInfo/Create";
        if ($this->useGroupApi) {
            $url = "Reservation/TempCustInfo/TempOrgCreate";
            $this->switchGroup();
        }

        $response = $this->post($url, [
            'form_params' => $data
        ]);

        $body = $response->getBody()->getContents();
        $result = json_decode($body, true);
        $statusCode = data_get($result, 'statusCode');
        if (!$statusCode) {
            Log::debug("错误的Status 返回码", [$data]);
            return [
                'a_status' => A_STATUS_ARCHIVE_ERROR,
                'log' => "建档失败: 无法识别的结果",
                'crm_response' => $body,
            ];
        }

        if ($statusCode !== '200') {
            $message = data_get($result, 'message');
            $phone = data_get($data, 'Phone');
            if (preg_match("/(UQ_TEMP_CUST_INFO_ID_PHONE|电话已存在|唯一)/", $message) || $this->checkPhoneIsArchive($phone)) {
                return [
                    'a_status' => A_STATUS_ARCHIVE_REPEAT,
                    'log' => '手机号码已建档',
                    'crm_response' => $body,
                ];
            } else {
                return [
                    'a_status' => A_STATUS_ARCHIVE_ERROR,
                    'log' => "建档失败: {$message}",
                    'crm_response' => $body,
                ];
            }
        }


        return [
            'a_status' => A_STATUS_ARCHIVE_SUCCESS,
            'log' => "建档成功",
            'crm_response' => $body,
        ];

    }

    public function getCustomerTypeList(): array
    {
        $html = $this->ReservationTempCustInfoCreateView();
        preg_match_all('/data-chid="(\w+)"[\n\t\w\-=" ]+[\t\n>]+(.*?)</', $html, $customerTypeList);
        $originData = data_get($customerTypeList, 0);
        if (!$originData) return [];

        $keyData = data_get($customerTypeList, 1);
        $nameData = data_get($customerTypeList, 2);
        $result = [];
        foreach ($originData as $index => $value) {
            if (!Str::contains($value, "data-issalon="))
                continue;
            $result[$keyData[$index]] = $nameData[$index];
        }
        return $result;
    }

    public function BaseDataManageCustMediaSourceIndex()
    {
        $url = $this->useGroupApi ? "BaseDataManage/CustMediaSourceOrg/Index" : "BaseDataManage/CustMediaSource/Index";

        $response = $this->post($url, [
            'form_params' => [
                "MediaCode" => "",
                "MediaName" => "",
                "MediaDesc" => "",
                "MediaTypeId" => "",
                "IsDisplay" => "Y",
                "pageSize" => "9800",
                "pageCurrent" => "1",
                "orderField" => "",
                "orderDirection" => "",
                "total" => "",
            ]
        ]);
        return $response->getBody()->getContents();
    }

    public function getMediaTypeList(): array
    {
        $html = $this->BaseDataManageCustMediaSourceIndex();
        preg_match_all('/option value="([\dA-Z]{10,})">(.*?)</', $html, $parentList);
        $originData = data_get($parentList, 0);
        $parentResult = [];

        if ($originData) {
            $keyData = data_get($parentList, 1);
            $nameData = data_get($parentList, 2);

            $t = parserHtmlTableToObject($html, '.table', 'innerText');
            $result = collect($t)
                ->map(function ($item) {
                    return [
                        'key' => $item['value'],
                        'name' => $item['媒介名称'],
                        'parent_name' => $item['媒介类型']
                    ];
                });
            foreach ($originData as $index => $value) {
                $name = $nameData[$index];
                $parentResult[] = [
                    'key' => $keyData[$index],
                    'name' => $name,
                    'children' => $result->filter(function ($item) use ($name) {
                        return $item['parent_name'] === $name;
                    })->values()->toArray()
                ];
            }
        }
        return $parentResult;
    }

    public function CommonAreaCommonEmpName()
    {
        $response = $this->get('CommonArea/Common/EmpName?term=');
        $body = $response->getBody()->getContents();
        $result = json_decode($body, true);
        return collect($result);
    }

    public function getAllUserList(): array
    {
        $data = [];
        $arr = $this->CommonAreaCommonEmpName();
        foreach ($arr as $item) {
            $val = $item['value'];
            preg_match('/\(([A-Za-z\-_\d]+)\)/', $val, $empResult);
            $code = data_get($empResult, 1);
            $item['code'] = $code;
            $data[$code] = $item;
        }

        return $data;
    }

    public function getUserIdOfCode($code)
    {

        $arr = $this->CommonAreaCommonEmpName();
        $result = $arr->first(function ($item) use ($code) {
            return Str::contains($item['value'], "($code)");
        });
        if (!$result) {
            $html = $this->ReservationTempCustSearchCompayIndex();
            preg_match('/value="([\dA-Z]{10,})"[\t\n>]+(.+\(' . $code . '\))/', $html, $userData);
            Log::debug("测试人员 ReservationTempCustSearchCompayIndex", [$userData]);
            if (!data_get($userData, 1)) {
                $html = $this->ReservationTempCustInfoCreateView();
                preg_match('/value="([\dA-Z]{10,})"[\t\n>]+(.+\(' . $code . '\))/', $html, $userData);
                Log::debug("测试人员 ReservationTempCustInfoCreateView", [$userData]);
            }

            return [
                'id' => data_get($userData, 1),
                'value' => data_get($userData, 2),
            ];
        }
        return $result;
    }


    public function ReportCenterPerformanceQueryExportExcel($data)
    {
        $data = array_merge(ClientConstants::ReportCenterPerformanceQueryExportExcelBaseForm, $data);
        return $this->postExcel('/ReportCenter/PerformanceQuery/ExportExcel', [
            'form_params' => $data,
        ]);
    }


    public function ReservationTempCustSearchTempCustSearchExportExcel($data)
    {
        $data = array_merge(ClientConstants::ReservationTempCustSearchTempCustSearchExportExcelBaseForm, $data);
        return $this->postExcel('/Reservation/TempCustSearch/TempCustSearchExportExcel', [
            'form_params' => $data,
            'timeout' => 160,
            'read_timeout' => 160,
            'connect_timeout' => 160,
        ], 'xls');
    }

    public function ReservationReservationSearchReservationSearchExportExcel($data)
    {
        $data = array_merge(ClientConstants::ReservationReservationSearchReservationSearchExportExcelBaseForm, $data);
        return $this->postExcel('/Reservation/ReservationSearch/ReservationSearchExportExcel', [
            'form_params' => $data,
            'timeout' => 160,
            'read_timeout' => 160,
            'connect_timeout' => 160,
        ], 'xls');
    }

    public static function make(): CrmClient|HongMaiClient
    {
        if (!self::$makeCache)
            self::$makeCache = new static();
        return self::$makeCache;
    }

    public static function checkPhoneIsArchive($phone): ?bool
    {
        try {
            $result = static::make()->ReservationTempCustInfoIndex([
                "Phone" => $phone
            ]);
            Log::debug("查询CRM预约单是否创建 $phone", [$result]);
            if ($result === null)
                return null;
            return !!count($result);
        } catch (\Exception $exception) {
            return false;
        }
    }

    public static function getPhoneArchiveInfo($phone)
    {
        try {
            $result = static::make()->ReservationTempCustInfoIndex([
                "Phone" => $phone
            ]);
            if (!$result || !count($result)) return null;
            $item = $result->first();
            if (!$item) return null;
            return $item;
        } catch (\Exception $exception) {
            return null;
        }
    }


    public static function getExecuteData($data)
    {
        return self::make()->ReportCenterPerformanceQueryExportExcel($data);
    }

    public static function getTempCustData($data)
    {
        return self::make()->ReservationReservationSearchReservationSearchExportExcel($data);
    }

    /**
     * @throws \Exception
     */
    public static function test()
    {
        $client = self::make();
        $client->getAllUserList();
    }


}
